package com.fangcang.elasticsearch;

import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortBuilders;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSONObject;

public class EsQueryService {
	
	public static final int SCROLL_SIZE = 10;

	public List<String> filterSearch(TransportClient client, List<EsQueryParam> params, String index,
			String indexType) {

		List<String> datas = new ArrayList<String>();
		BoolQueryBuilder qb = QueryBuilders.boolQuery();

		if (CollectionUtils.isEmpty(params)) {
			return datas;
		}

		SearchResponse searchResponse = client.prepareSearch(index).setTypes(indexType).setQuery(qb).get();
		SearchHits hits = searchResponse.getHits();
		SearchHit[] hits2 = hits.getHits();
		for (SearchHit sh : hits2) {
			Map<String, Object> source = sh.getSource();
			datas.add(JSONObject.toJSONString(source));
			System.out.println(JSONObject.toJSONString(source));
		}

		return datas;
	}

	/**
	 * 按时间段查询
	 * 
	 * @param client
	 * @param index
	 * @param indexType
	 * @param fromTime
	 * @param endTime
	 */
	public List<Map<String, Object>> searchByTimes(TransportClient client, EsQueryParam param) {
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		String index = param.getIndex();
		String indexType = param.getIndexType();
		String field = param.getField();

		// 每次查询只能查询十分钟的数据00-09:59 50:00-59:59
		String fromTime = param.getFromTime().format(DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss"));
//		if (StringUtils.isEmpty(fromTime)) {
//			fromTime = LocalDateTime.now().minusMinutes(10).toString();
//		}
		String endTime = param.getEndTime().format(DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss"));;
//		if (StringUtils.isEmpty(endTime)) {
//			endTime = LocalDateTime.now().toString();
//		}
//		// 如果endTime-fromTime>10分钟，以endTime-10分钟计算
//		LocalDateTime before10Min = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).minusMinutes(10);
//		if (before10Min.isAfter(LocalDateTime.parse(fromTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))) {
//			fromTime = before10Min.toString();
//		}
		
		//其他查询条件
		
		//分页

		QueryBuilder query = QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery(field).from(fromTime).to(endTime));
		SearchResponse searchResponse = client.prepareSearch(index).setTypes(indexType).setQuery(query).get();
		SearchHits hits = searchResponse.getHits();
		SearchHit[] hits2 = hits.getHits();
		for (SearchHit sh : hits2) {
			Map<String, Object> source = sh.getSource();
			result.add(source);
			System.out.println(JSONObject.toJSONString(source));
		}
		return result;
	}
	
	
	public void scrollPageSearch(TransportClient client, String index, List<EsClauseDto> clause) {
		BoolQueryBuilder builder = QueryBuilders.boolQuery();
		if(!CollectionUtils.isEmpty(clause)) {
			for(EsClauseDto where : clause) {
				if(where.isMust()) {
					builder.must(QueryBuilders.commonTermsQuery(where.getFeildName(), where.getFieldValue()));
				}
				if(where.isShould()) {
					builder.should(QueryBuilders.commonTermsQuery(where.getFeildName(), where.getFieldValue()));
				}
			}
		}
		System.out.println("scroll 模式启动！");
		Date begin = new Date();
		SearchResponse scrollResponse = client.prepareSearch(index)
			.addSort(SortBuilders.fieldSort("createTime"))
		    //.setSearchType(SearchType.SCAN)   //在ES 5.x版本中不存在SearchType.SCAN用法，可以用addSort(SortBuilders.fieldSort("_doc"))
		    .setSize(SCROLL_SIZE) //实际返回的数量为size*index的主分片个数（在ES 5.x版本中，返回的数据量就是参数中指定的数据量）
		    .setScroll(TimeValue.timeValueMinutes(1)) 
		    .setQuery(builder)
		    .execute().actionGet();  
		int sum=0;
		SearchHit[] hits2 = scrollResponse.getHits().getHits();
		for (SearchHit sh : hits2) {
			Map<String, Object> source = sh.getSource();
			System.out.println(JSONObject.toJSONString(source));
		}
		sum += hits2.length;
		long count = scrollResponse.getHits().getTotalHits();//获取所有记录，第一次不返回数据(在ES 5.x版本中，第一次有数据返回)
		for(; sum<count; ){
		    scrollResponse = scrollPageSearchByScrollId(client, scrollResponse.getScrollId());
		    sum += scrollResponse.getHits().getHits().length;
//		    System.out.println("总量"+count+" 已经查到"+sum);
		}
		Date end = new Date();
		System.out.println("耗时: "+(end.getTime()-begin.getTime()));
	}
	
	
	public SearchResponse scrollPageSearchByScrollId(TransportClient client, String scrollId) {
		SearchResponse scrollResponse = client.prepareSearchScroll(scrollId)  
			        .setScroll(TimeValue.timeValueMinutes(8))  
			    .execute().actionGet();
		 return scrollResponse;
	}
	
	
	public List<Map<String, Object>> getSearchResult(TransportClient client, String scrollId){
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		SearchResponse scrollResponse = scrollPageSearchByScrollId(client, scrollId);
		if(scrollResponse == null || scrollResponse.getHits() == null || scrollResponse.getHits().getHits() == null) {
			return result;
		}
		SearchHit[] hits = scrollResponse.getHits().getHits();
		for(SearchHit hit: hits) {
			result.add(hit.getSource());
		}
		
		return result;
	}

}
